package com.empire.module.member.service.internetaccount;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.empire.framework.common.exception.util.ServiceExceptionUtil;
import com.empire.module.member.controller.admin.internetaccountfollow.InternetAccountFollowDO;
import com.empire.module.member.dal.dataobject.accounttype.AccountTypeDO;
import com.empire.module.member.dal.dataobject.relation.NodeDo;
import com.empire.module.member.dal.dataobject.relation.RelationshipDo;
import com.empire.module.member.dal.dataobject.user.MemberUserDO;
import com.empire.module.member.dal.mysql.accounttype.AccountTypeMapper;
import com.empire.module.member.dal.mysql.internetaccountfollow.InternetAccountFollowMapper;
import com.empire.module.member.dal.mysql.relationship.NodeMapper;
import com.empire.module.member.dal.mysql.relationship.RelationshipMapper;
import com.empire.module.member.dal.mysql.user.MemberUserMapper;
import com.empire.module.member.enums.ErrorCodeConstants;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import com.empire.module.member.controller.admin.internetaccount.vo.*;
import com.empire.module.member.dal.dataobject.internetaccount.InternetAccountDO;
import com.empire.framework.common.pojo.PageResult;
import com.empire.framework.common.util.object.BeanUtils;

import com.empire.module.member.dal.mysql.internetaccount.InternetAccountMapper;

import javax.annotation.Resource;

import java.util.*;
import java.util.stream.Collectors;

import static com.empire.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.empire.module.member.enums.ErrorCodeConstants.*;

/**
 * 互联网账号 Service 实现类
 *
 * @author 主席大人
 */
@Service
@Validated
public class InternetAccountServiceImpl implements InternetAccountService {

    @Resource
    private InternetAccountMapper internetAccountMapper;
    @Resource
    private NodeMapper nodeMapper;
    @Resource
    private RelationshipMapper relationshipMapper;
    @Resource
    private MemberUserMapper memberUserMapper;
    @Resource
    private AccountTypeMapper accountTypeMapper;
    @Resource
    private InternetAccountFollowMapper internetAccountFollowMapper;

    @Override
    @Transactional
    public Long createInternetAccount(InternetAccountSaveReqVO createReqVO) {
        // 转换为DO对象
        InternetAccountDO account = BeanUtils.toBean(createReqVO, InternetAccountDO.class);
        Long personId = account.getPersonId();

        // 检查账号是否已存在（personId、accountTypeId、username唯一）
        if (isAccountExists(account)) {
            InternetAccountDO existingAccount = getExistingAccount(account);
            return existingAccount.getId();
        }

        // 插入新账号
        internetAccountMapper.insert(account);

        // 处理节点及关系
        handleNodesAndRelationships(personId, account);

        return account.getId();
    }

    @Override
    @Transactional
    public void updateInternetAccount(InternetAccountSaveReqVO updateReqVO) {
        // 校验存在
        InternetAccountDO oldAccount = validateInternetAccountExists(updateReqVO.getId());
        Long personId = oldAccount.getPersonId();
        Long oldAccountTypeId = oldAccount.getAccountTypeId();
        String oldUsername = oldAccount.getUsername();

        // 转换为更新对象
        InternetAccountDO updateObj = BeanUtils.toBean(updateReqVO, InternetAccountDO.class);
        Long newAccountTypeId = updateObj.getAccountTypeId();
        String newUsername = updateObj.getUsername();

        // 处理节点和关系变更
        if (!Objects.equals(oldAccountTypeId, newAccountTypeId)) {
            // 类型发生变化：处理旧类型相关节点和关系
            handleTypeChange(personId, oldAccountTypeId, oldUsername);
        } else if (!Objects.equals(oldUsername, newUsername)) {
            // 类型不变，账号名变化：处理旧账号相关节点和关系
            handleUsernameChange(personId, oldAccountTypeId, oldUsername);
        }

        // 更新账号信息
        internetAccountMapper.updateById(updateObj);

        // 重建新的节点和关系（复用创建时的逻辑）
        handleNodesAndRelationships(personId, updateObj);
    }

    @Override
    @Transactional
    public void deleteInternetAccount(Long id) {
        // 校验存在
        InternetAccountDO accountDO = validateInternetAccountExists(id);
        Long personId = accountDO.getPersonId();
        Long accountTypeId = accountDO.getAccountTypeId();
        String username = accountDO.getUsername();

        // 删除账号记录
        internetAccountMapper.deleteById(id);

        // 处理关联的节点和关系
        handleAccountDeletion(personId, accountTypeId, username);
    }

    /**
     * 处理账号类型变更时的旧节点和关系清理
     */
    private void handleTypeChange(Long personId, Long oldAccountTypeId, String oldUsername) {
        // 1. 获取旧类型节点
        AccountTypeDO oldAccountType = accountTypeMapper.selectById(oldAccountTypeId);
        if (oldAccountType == null) {
            return;
        }
        NodeDo oldTypeNode = getNodeByCondition(personId, oldAccountType.getName(), 2);
        if (oldTypeNode == null) {
            return;
        }

        // 2. 获取旧账号节点
        NodeDo oldAccountNode = getNodeByCondition(personId, oldUsername, 3);

        // 3. 删除旧类型-旧账号的关系
        if (oldAccountNode != null) {
            deleteRelationship(personId, oldTypeNode.getId(), oldAccountNode.getId());
            // 删除旧账号节点
            nodeMapper.deleteById(oldAccountNode.getId());
        }

        // 4. 检查旧类型节点是否还有其他账号关联
        if (hasRelatedAccountNodes(personId, oldTypeNode.getId())) {
            // 4.1 获取人员节点
            MemberUserDO member = memberUserMapper.selectById(personId);
            NodeDo personNode = member != null ? getNodeByCondition(personId, member.getName(), 1) : null;

            // 4.2 删除人员-旧类型的关系
            if (personNode != null) {
                deleteRelationship(personId, personNode.getId(), oldTypeNode.getId());
            }

            // 4.3 删除旧类型节点
            nodeMapper.deleteById(oldTypeNode.getId());
        }
    }

    /**
     * 处理账号名变更时的旧节点和关系清理
     */
    private void handleUsernameChange(Long personId, Long accountTypeId, String oldUsername) {
        // 1. 获取类型节点
        AccountTypeDO accountType = accountTypeMapper.selectById(accountTypeId);
        if (accountType == null) {
            return;
        }
        NodeDo typeNode = getNodeByCondition(personId, accountType.getName(), 2);
        if (typeNode == null) {
            return;
        }

        // 2. 获取旧账号节点
        NodeDo oldAccountNode = getNodeByCondition(personId, oldUsername, 3);
        if (oldAccountNode == null) {
            return;
        }

        // 3. 删除类型-旧账号的关系
        deleteRelationship(personId, typeNode.getId(), oldAccountNode.getId());

        // 4. 删除旧账号节点
        nodeMapper.deleteById(oldAccountNode.getId());

        // 5. 检查类型节点是否还有其他账号关联
        if (hasRelatedAccountNodes(personId, typeNode.getId())) {
            // 5.1 获取人员节点
            MemberUserDO member = memberUserMapper.selectById(personId);
            NodeDo personNode = member != null ? getNodeByCondition(personId, member.getName(), 1) : null;

            // 5.2 删除人员-类型的关系
            if (personNode != null) {
                deleteRelationship(personId, personNode.getId(), typeNode.getId());
            }

            // 5.3 删除类型节点
            nodeMapper.deleteById(typeNode.getId());
        }
    }

    /**
     * 处理账号删除时的节点和关系清理
     */
    private void handleAccountDeletion(Long personId, Long accountTypeId, String username) {
        // 1. 获取类型节点
        AccountTypeDO accountType = accountTypeMapper.selectById(accountTypeId);
        if (accountType == null) {
            return;
        }
        NodeDo typeNode = getNodeByCondition(personId, accountType.getName(), 2);
        if (typeNode == null) {
            return;
        }

        // 2. 获取账号节点
        NodeDo accountNode = getNodeByCondition(personId, username, 3);
        if (accountNode == null) {
            return;
        }

        // 3. 删除类型-账号的关系
        deleteRelationship(personId, typeNode.getId(), accountNode.getId());

        // 4. 删除账号节点
        nodeMapper.deleteById(accountNode.getId());

        // 5. 检查类型节点是否还有其他账号关联
        if (hasRelatedAccountNodes(personId, typeNode.getId())) {
            // 5.1 获取人员节点
            MemberUserDO member = memberUserMapper.selectById(personId);
            NodeDo personNode = member != null ? getNodeByCondition(personId, member.getName(), 1) : null;

            // 5.2 删除人员-类型的关系
            if (personNode != null) {
                deleteRelationship(personId, personNode.getId(), typeNode.getId());
            }

            // 5.3 删除类型节点
            nodeMapper.deleteById(typeNode.getId());
        }
    }

    /**
     * 检查类型节点是否有关联的账号节点
     */
    private boolean hasRelatedAccountNodes(Long personId, Long typeNodeId) {
        LambdaQueryWrapper<RelationshipDo> query = new LambdaQueryWrapper<>();
        query.eq(RelationshipDo::getPersonId, personId)
                .eq(RelationshipDo::getSourceId, typeNodeId);
        // 统计关联的关系数量
        return relationshipMapper.selectCount(query) <= 0;
    }

    /**
     * 删除指定的关系
     */
    private void deleteRelationship(Long personId, Long sourceId, Long targetId) {
        LambdaQueryWrapper<RelationshipDo> query = new LambdaQueryWrapper<>();
        query.eq(RelationshipDo::getPersonId, personId)
                .eq(RelationshipDo::getSourceId, sourceId)
                .eq(RelationshipDo::getTargetId, targetId);
        relationshipMapper.delete(query);
    }

    private InternetAccountDO validateInternetAccountExists(Long id) {
        InternetAccountDO internetAccountDO = internetAccountMapper.selectById(id);
        if (internetAccountDO == null) {
            throw exception(INTERNET_ACCOUNT_NOT_EXISTS);
        }
        return internetAccountDO;
    }

    @Override
    public InternetAccountDO getInternetAccount(Long id) {
        return internetAccountMapper.selectById(id);
    }

    @Override
    public PageResult<InternetAccountDO> getInternetAccountPage(InternetAccountPageReqVO pageReqVO) {
        return internetAccountMapper.selectPage(pageReqVO);
    }


    /**
     * 检查账号是否已存在
     */
    private boolean isAccountExists(InternetAccountDO account) {
        return getExistingAccount(account) != null;
    }

    /**
     * 获取已存在的账号
     */
    private InternetAccountDO getExistingAccount(InternetAccountDO account) {
        LambdaQueryWrapper<InternetAccountDO> query = new LambdaQueryWrapper<>();
        query.eq(InternetAccountDO::getAccountTypeId, account.getAccountTypeId())
                .eq(InternetAccountDO::getPersonId, account.getPersonId())
                .eq(InternetAccountDO::getUsername, account.getUsername())
                .last("limit 1");
        return internetAccountMapper.selectOne(query);
    }

    /**
     * 处理节点及关系创建
     */
    private void handleNodesAndRelationships(Long personId, InternetAccountDO account) {
        // 创建人员节点
        NodeDo personNode = createNodeIfNotExists(personId,
                getPersonName(personId), 1, 25);

        // 创建账号类型节点并建立与人员节点的关系
        NodeDo accountTypeNode = createAccountTypeNode(personId, account.getAccountTypeId());
        createRelationshipIfNotExists(personId, personNode.getId(), accountTypeNode.getId());

        // 创建账号节点并建立与类型节点的关系
        NodeDo accountNode = createNodeIfNotExists(personId,
                account.getUsername(), 3, 15);
        createRelationshipIfNotExists(personId, accountTypeNode.getId(), accountNode.getId());
    }

    /**
     * 获取人员名称
     */
    private String getPersonName(Long personId) {
        MemberUserDO member = memberUserMapper.selectById(personId);
        return member != null ? member.getName() : "";
    }

    /**
     * 创建账号类型节点
     */
    private NodeDo createAccountTypeNode(Long personId, Long accountTypeId) {
        AccountTypeDO accountType = accountTypeMapper.selectById(accountTypeId);
        return createNodeIfNotExists(personId,
                accountType != null ? accountType.getName() : "", 2, 20);
    }

    /**
     * 若节点不存在则创建并返回
     */
    private NodeDo createNodeIfNotExists(Long personId, String name, Integer group, Integer size) {
        // 检查节点是否存在
        NodeDo existingNode = getNodeByCondition(personId, name, group);
        if (existingNode != null) {
            return existingNode;
        }

        // 创建新节点
        NodeDo newNode = new NodeDo();
        newNode.setPersonId(personId);
        newNode.setName(name);
        newNode.setGroup(group);
        newNode.setSize(size);
        nodeMapper.insert(newNode);
        return newNode;
    }

    /**
     * 根据条件查询节点
     */
    private NodeDo getNodeByCondition(Long personId, String name, Integer group) {
        LambdaQueryWrapper<NodeDo> query = new LambdaQueryWrapper<>();
        query.eq(NodeDo::getPersonId, personId)
                .eq(NodeDo::getName, name)
                .eq(NodeDo::getGroup, group)
                .last("limit 1");
        return nodeMapper.selectOne(query);
    }

    /**
     * 若关系不存在则创建
     */
    private void createRelationshipIfNotExists(Long personId, Long sourceId, Long targetId) {
        // 这里可根据实际需求添加关系存在性检查
        RelationshipDo relationship = new RelationshipDo();
        relationship.setPersonId(personId);
        relationship.setSourceId(sourceId);
        relationship.setTargetId(targetId);
        relationship.setValue(3);
        relationshipMapper.insert(relationship);
    }

    // ------------------- 新增：相似账号分析实现 -------------------
    @Override
    public SimilarAccountAnalysisRespVO analyzeSimilarAccounts(SimilarAccountAnalysisReqVO reqVO) {
        // 1. 校验目标账号是否存在
        InternetAccountDO targetAccount = validateInternetAccountExists(reqVO.getAccountId());
        // 2. 获取目标账号的粉丝列表（从粉丝关系表查询）
        Set<String> targetFanUuids = getAccountFanUuids(targetAccount.getUserGenUuid());
        if (CollectionUtils.isEmpty(targetFanUuids)) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.INTERNET_ACCOUNT_FAN_EMPTY, targetAccount.getUsername());
        }
        int targetFanCount = targetFanUuids.size();

        // 3. 查询同类型的其他账号（排除目标账号自身）
        List<InternetAccountDO> sameTypeAccounts = getSameTypeOtherAccounts(targetAccount);
        if (CollectionUtils.isEmpty(sameTypeAccounts)) {
            SimilarAccountAnalysisRespVO result = new SimilarAccountAnalysisRespVO();
            result.setTargetAccount(buildTargetAccountVO(targetAccount));
            result.setSimilarAccounts(Collections.emptyList());
            result.setAnalysisTime(System.currentTimeMillis() / 1000);
            return result;
        }

        // 4. 遍历计算每个账号与目标账号的相似性（共同粉丝数、重叠率）
        List<SimilarAccountVO> similarAccountList = new ArrayList<>();
        for (InternetAccountDO account : sameTypeAccounts) {
            // 4.1 获取当前账号的粉丝列表
            Set<String> currentFanUuids = getAccountFanUuids(account.getUserGenUuid());
            if (CollectionUtils.isEmpty(currentFanUuids)) {
                continue; // 无粉丝的账号跳过
            }

            // 4.2 计算共同粉丝数（求两个集合的交集）
            int commonFanCount = CollectionUtils.intersection(targetFanUuids, currentFanUuids).size();
            // 4.3 计算粉丝重叠率（按目标账号粉丝数为基准）
            int overlapRate = (int) Math.round(((double) commonFanCount / targetFanCount) * 100);

            // 4.4 按阈值筛选相似账号
            if (overlapRate >= reqVO.getOverlapThreshold()) {
                SimilarAccountVO similarVO = BeanUtils.toBean(account, SimilarAccountVO.class);
                // 补充账号类型名称
                AccountTypeDO accountType = accountTypeMapper.selectById(account.getAccountTypeId());
                similarVO.setAccountTypeName(accountType != null ? accountType.getName() : "未知类型");
                // 补充相似性数据
                similarVO.setCommonFanCount(commonFanCount);
                similarVO.setOverlapRate(overlapRate);
                similarAccountList.add(similarVO);
            }
        }

        // 5. 对相似账号按重叠率降序排序
        similarAccountList.sort((a, b) -> Integer.compare(b.getOverlapRate(), a.getOverlapRate()));

        // 6. 封装最终结果
        SimilarAccountAnalysisRespVO result = new SimilarAccountAnalysisRespVO();
        result.setTargetAccount(buildTargetAccountVO(targetAccount));
        result.setSimilarAccounts(similarAccountList);
        result.setAnalysisTime(System.currentTimeMillis() / 1000);
        return result;
    }

    /**
     * 获取某个账号的粉丝UUID列表（从member_internet_account_follow表查询）
     * @param userGenUuid 账号的唯一标识（user_gen_uuid）
     * @return 粉丝的user_gen_uuid集合
     */
    private Set<String> getAccountFanUuids(String userGenUuid) {
        LambdaQueryWrapper<InternetAccountFollowDO> query = new LambdaQueryWrapper<>();
        // 粉丝关系表中：followed_user_gen_uuid = 被关注者（当前账号），follow_user_gen_uuid = 粉丝
        query.eq(InternetAccountFollowDO::getFollowedUserGenUuid, userGenUuid)
                .select(InternetAccountFollowDO::getFollowUserGenUuid); // 只查需要的字段，提高效率
        List<InternetAccountFollowDO> followList = internetAccountFollowMapper.selectList(query);
        // 转换为粉丝UUID集合
        return followList.stream()
                .map(InternetAccountFollowDO::getFollowUserGenUuid)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());
    }

    /**
     * 查询与目标账号同类型的其他账号（排除自身）
     */
    private List<InternetAccountDO> getSameTypeOtherAccounts(InternetAccountDO targetAccount) {
        LambdaQueryWrapper<InternetAccountDO> query = new LambdaQueryWrapper<>();
        query.eq(InternetAccountDO::getAccountTypeId, targetAccount.getAccountTypeId()) // 同账号类型
                .ne(InternetAccountDO::getId, targetAccount.getId()) // 排除自身
                .eq(InternetAccountDO::getDeleted, false) // 未删除
                .isNotNull(InternetAccountDO::getUserGenUuid) // 有唯一标识的账号
                .gt(InternetAccountDO::getFanCount, 0); // 有粉丝的账号（无粉丝的无需分析）
        return internetAccountMapper.selectList(query);
    }

    /**
     * 构建目标账号VO（封装返回给前端的简要信息）
     */
    private SimilarAccountAnalysisRespVO.TargetAccountVO buildTargetAccountVO(InternetAccountDO targetAccount) {
        SimilarAccountAnalysisRespVO.TargetAccountVO targetVO = new SimilarAccountAnalysisRespVO.TargetAccountVO();
        targetVO.setId(targetAccount.getId());
        targetVO.setUsername(targetAccount.getUsername());
        targetVO.setNickname(targetAccount.getNickname());
        targetVO.setFanCount(targetAccount.getFanCount());
        return targetVO;
    }
}